package com.bort.system.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.bort.system.info.CheckOutResult;
import com.bort.system.info.DeskInfo;
import com.bort.system.mapper.*;
import com.bort.system.model.*;
import com.bort.system.service.AsyncService;
import com.bort.system.utils.Result;
import org.apache.commons.lang3.time.DateFormatUtils;
import org.springframework.core.annotation.Order;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.util.Date;
import java.util.List;

@Service
public class AsyncServiceImpl implements AsyncService {

    @Resource
    TDeskMapper deskMapper;

    @Resource
    TGameLogMapper gameLogMapper;

    @Resource
    CartMapper cartMapper;

    @Resource
    OrderMapper orderMapper;

    @Resource
    CartOrderMapper cartOrderMapper;

    @Resource
    GoodsMapper goodsMapper;

    @Async
    @Override
    public void closeDeskAsync(DeskInfo data,Date endTime,BigDecimal amount,BigDecimal pay,Integer userId) {
        TDesk entity = deskMapper.selectById(data.getId());
        TGameLog gameLog = gameLogMapper.selectById(data.getLogId());

        CheckOutResult result = checkOut(gameLog.getCreateTime(), endTime, entity.getPrice());

        BigDecimal goMinute = result.getHour().multiply(new BigDecimal(60)).add(result.getMinute());
        gameLog.setTotalTime(goMinute.intValue());
        BigDecimal goHour = result.getHour().add(result.getMinute().divide(new BigDecimal(60),2,BigDecimal.ROUND_DOWN));

        entity.setStatus("1");
        entity.setUpdateTime(endTime);
        BigDecimal totalTime = entity.getTotalTime() != null?entity.getTotalTime():new BigDecimal(0);
        entity.setTotalTime(totalTime.add(goHour));

        BigDecimal totalIncome = entity.getTotalIncome() != null?entity.getTotalIncome():new BigDecimal(0);
        entity.setTotalIncome(totalIncome.add(pay));
        deskMapper.updateById(entity);

        Date now = new Date();
        List<Cart> carts = data.getCartList();
        if(carts == null || carts.size() == 0){
            QueryWrapper<Cart> wrapper = new QueryWrapper<>();
            wrapper.eq("DESK_ID",data.getId());
            wrapper.eq("CART_STATUS",1);
            carts = cartMapper.selectList(wrapper);
        }
        Integer orderId = createOrder(data.getId(),pay,now,carts,userId);
        gameLog.setOrderId(orderId);
        if(carts != null && carts.size() > 0){
            for (Cart cart : carts) {
                CartOrder cartOrder = new CartOrder();
                cartOrder.setCartId(cart.getId());
                cartOrder.setOrderId(orderId);
                cartOrder.setCreateTime(now);
                cartOrderMapper.insert(cartOrder);
                cart.setCartStatus(2);
                cartMapper.updateById(cart);
            }
        }

        gameLog.setEndTime(endTime);
        gameLog.setAmount(amount);
        gameLog.setIncome(pay);
        gameLog.setStatus("3");
        gameLogMapper.updateByPrimaryKeySelective(gameLog);
    }

    @Order
    public CheckOutResult checkOut(Date startTime, Date endTime, BigDecimal price) {
        long startSecond = startTime.getTime()/1000;
        long endSecond = endTime.getTime()/1000;
        long timeLong = endSecond - startSecond;
        BigDecimal hours = new BigDecimal(timeLong).divide(new BigDecimal(3600),0,BigDecimal.ROUND_DOWN);
        BigDecimal minutes = (new BigDecimal(timeLong/60)).subtract(hours.multiply(new BigDecimal(60)));
        BigDecimal hoursAmount = hours.multiply(price);
        BigDecimal minutesAmount = minutes.multiply(price).divide(new BigDecimal(60),2,BigDecimal.ROUND_DOWN);
        BigDecimal total = hoursAmount.add(minutesAmount).setScale(0,BigDecimal.ROUND_HALF_UP);
        return new CheckOutResult(total,hours,minutes);
    }

    @Order
    public Integer createOrder(Integer deskId,BigDecimal pay, Date now,List<Cart> carts,Integer userId){
        TOrder order = new TOrder();
        order.setBusinessType(1);
        String orderNum = "ON"+ DateFormatUtils.format(now, "yyMMddHHmmss");
        order.setOrderNo(orderNum);
        order.setCreateTime(now);
        order.setOrderStatus(1);
        order.setDeskId(deskId);
        order.setCreateUserId(userId);
        order.setRealPay(pay);
        if(carts != null && carts.size() > 0){
            BigDecimal orderTotal = carts.stream().map(cart -> cart.getTotalAmount()).reduce(BigDecimal.ZERO, (c1, c2) -> c1.add(c2));
            Integer goodsSum = carts.stream().map(mp -> mp.getNum()).reduce(0, (n1, n2) -> n1 + n2);
            order.setGoodsNum(goodsSum);
            order.setTotal(orderTotal);
        }
        orderMapper.insert(order);
        return order.getId();
    }

    @Async
    @Override
    public void putInCart(Goods indexGoods, String orderNo, int num, int deskId, String playerName,Integer userId) {
        QueryWrapper<Cart> wrapper = new QueryWrapper<>();
        wrapper.eq("goods_id",indexGoods.getId());
        wrapper.eq("desk_id",deskId);
        wrapper.eq("player_name",playerName);
        wrapper.eq("cart_status",1);
        List<Cart> carts = cartMapper.selectList(wrapper);
        Cart cart = null;
        if(carts != null && carts.size() > 0){
            cart = carts.get(0);
            cart.setNum(cart.getNum() + num);
            BigDecimal total = indexGoods.getPrice().multiply(new BigDecimal(cart.getNum()));
            total.setScale(2,BigDecimal.ROUND_HALF_UP);
            cart.setTotalAmount(total);
            cartMapper.updateById(cart);
        }else{
            cart = new Cart();
            cart.setNum(num);
            cart.setCartStatus(1);
            cart.setGoodsId(indexGoods.getId());
            cart.setGoodsName(indexGoods.getGoodsName());
            cart.setImgUrl(indexGoods.getGoodsImage());
            cart.setGoodsPrice(indexGoods.getPrice());
            cart.setDeskId(deskId);
            cart.setPlayerName(playerName);
            BigDecimal total = indexGoods.getPrice().multiply(new BigDecimal(num));
            total.setScale(2,BigDecimal.ROUND_HALF_UP);
            cart.setTotalAmount(total);
            cart.setCreateUserId(userId);
            cart.setCreateTime(new Date());
            cartMapper.insert(cart);
        }
        Goods goods = goodsMapper.selectById(indexGoods.getId());
        goods.setStock(goods.getStock() - num);
        goods.setSold(goods.getSold() + num);
        goodsMapper.updateById(goods);
    }

    @Async
    @Override
    public void removeCart(Cart cart) {
        Integer num = cart.getNum();
        cartMapper.deleteById(cart.getId());
        Goods goods = goodsMapper.selectById(cart.getGoodsId());
        goods.setStock(goods.getStock() + num);
        goods.setSold(goods.getSold() - num);
        goodsMapper.updateById(goods);
    }

    @Async
    @Override
    public void saveOrder(TOrder order) {
        orderMapper.insert(order);
    }


    @Async
    @Transactional
    @Override
    public Result sale(Goods indexGoods, String orderNo, int num,Integer userId) {
        indexGoods.setStock(indexGoods.getStock() - num);
        indexGoods.setSold(indexGoods.getSold() + num);
        int upd = goodsMapper.updateById(indexGoods);
        TOrder order = new TOrder();
        order.setGoodsId(indexGoods.getId());
        order.setOrderNo(orderNo);
        order.setGoodsNum(num);
        order.setGoodsPrice(indexGoods.getPrice());
        BigDecimal total = indexGoods.getPrice().multiply(new BigDecimal(num));
        total.setScale(2,BigDecimal.ROUND_HALF_UP);
        order.setTotal(total);
        order.setRealPay(total);
        order.setOrderStatus(1);
        order.setCreateTime(new Date());
        order.setCreateUserId(userId);
        orderMapper.insert(order);
        return Result.success();
    }

}

